package see.battle.server;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.util.ArrayList;
import java.util.Random;

import android.bluetooth.BluetoothSocket;

import see.battle.Const;
import see.battle.gui.Game.ResultProcessor;
import see.battle.message.InitializeMessage;
import see.battle.message.Message;
import see.battle.message.StartGameMessage;

public class Server implements Runnable {
  
  ArrayList<Message> _messagesLocal = new ArrayList<Message>();
  int _localNumberRead = 0;
  ArrayList<Message> _messagesGlobal = new ArrayList<Message>();
  int _globalNumberWrite = 0;
  ObjectInputStream _input;
  ObjectOutputStream _output;
  boolean _stop = false;
  private ResultProcessor _resultProcessor;

  public void set_resultProcessor(ResultProcessor resultProcessor) {
    _resultProcessor = resultProcessor;
  }
  
  public Server(BluetoothSocket bs) {
    try {
      _output = new ObjectOutputStream(bs.getOutputStream());
      _output.flush();
      _input = new ObjectInputStream(bs.getInputStream());
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
  
  private void startGame() {
    Random randomGenerator = new Random();
    int view = randomGenerator.nextInt(10000);
  
    Message ms = new StartGameMessage(System.currentTimeMillis(), 42, view);
    synchronized (_messagesLocal) {
      _messagesLocal.add(ms);
    }
    synchronized (_messagesGlobal) {
      _messagesGlobal.add(ms);
      while (_globalNumberWrite < _messagesGlobal.size()) {
        try {
          _output.writeObject(_messagesGlobal.get(_globalNumberWrite));
          ++_globalNumberWrite;
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
  
  private void initGame() {
    Message ms = new InitializeMessage(System.currentTimeMillis());
    synchronized (_messagesGlobal) {
      _messagesGlobal.add(ms);
      while (_globalNumberWrite < _messagesGlobal.size()) {
        try {
          _output.writeObject(_messagesGlobal.get(_globalNumberWrite));
          ++_globalNumberWrite;
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
   
  }
  
  public void stop() {
    _stop = true;
  }
  
  private void closeActivity() {
    try {
      _resultProcessor.call();
    } catch (Exception e1) {
      e1.printStackTrace();
    }
  }
  
  public void run() {
    while (true) {
      if (_stop) break; 
      Message m = null;
        try {
          m = (Message)_input.readObject();
        } catch (OptionalDataException e) {
          e.printStackTrace();
        } catch (ClassNotFoundException e) {
          e.printStackTrace();
        } catch (IOException e) {
          e.printStackTrace();
        }
      if (m != null) {
        if (m.type() != Const.initializeMessageType) {
          synchronized (_messagesLocal) {
            _messagesLocal.add(m); 
          }
        } else {
          System.err.println("Server Message about init is received");
          initGame();
          startGame();
        }
      }
    }
  }
  
  public Message getNextMessage() {
    synchronized (_messagesLocal) {
      if (_localNumberRead < _messagesLocal.size()) {
        Message m = _messagesLocal.get(_localNumberRead);
        _localNumberRead += 1;
        return m;
      } else {
        return null;
      }
    }
  }
  
  public void addMessage(Message m) {
    synchronized (_messagesGlobal) {
      _messagesGlobal.add(m);
      while (_globalNumberWrite < _messagesGlobal.size()) {
        try {
          if (_output != null) {
          _output.writeObject(_messagesGlobal.get(_globalNumberWrite));
          _output.flush();
          }
          ++_globalNumberWrite;
          
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}
